package mm.chensj.demo.ch01;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Lenovo
 * @title 根据认证规则处理
 * @project shiro-demo
 * @package mm.chensj.demo.ch01
 * @date: 2019-01-17 17:30
 */
public class AuthenticatorLogin {

    private static final Logger logger = LoggerFactory.getLogger(AuthenticatorLogin.class);

    /**
     * Authenticator的职责是验证用户帐号，是Shiro API中身份验证核心的入口点
     * 如果验证成功，将返回AuthenticationInfo验证信息；此信息中包含了身份及凭证；如果验证失败将抛出相应的AuthenticationException实现。
     * SecurityManager接口继承了Authenticator，另外还有一个ModularRealmAuthenticator实现，其委托给多个Realm进行验证，验证规则通过AuthenticationStrategy接口指定，默认提供的实现：
     *  FirstSuccessfulStrategy：只要有一个Realm验证成功即可，只返回第一个Realm身份验证成功的认证信息，其他的忽略；
     *  AtLeastOneSuccessfulStrategy：只要有一个Realm验证成功即可，和FirstSuccessfulStrategy不同，返回所有Realm身份验证成功的认证信息；
     *  AllSuccessfulStrategy：所有Realm验证成功才算成功，且返回所有Realm身份验证成功的认证信息，如果有一个失败就失败了。
     *
     * @param args
     */
    public static void main(String[] args){
        String iniName = "classpath:shiro.ini" ;
        String username = "zhang" ;
        String password = "123" ;
    }

    public static void login(String iniName,String username,String password){

        logger.info("ini-path:{}",iniName);
        //1、获取SecurityManager工厂，此处使用Ini配置文件初始化SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory(iniName);
        //2、获取SecurityManager
        SecurityManager manager = factory.getInstance();
        //3、设置SecurityManager作为默认使用的
        SecurityUtils.setSecurityManager(manager);
        //4、获取Subject
        Subject subject = SecurityUtils.getSubject();
        //5、创建用户Token
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        //6、登录用户
        try {
            subject.login(token);
        }catch (IncorrectCredentialsException incorrectCredentialsException){
            logger.error("用户名或密码输入错误:{}",incorrectCredentialsException.getMessage());
        }catch (UnknownAccountException unknownAccountException){
            logger.error("用户名不存在:{}",unknownAccountException.getMessage());
        }catch (AuthenticationException e){
            logger.error("认证其他错误:{}",e.getMessage());
            // 登录失败
        }
        logger.info("用户登录状态:{}",subject.isAuthenticated());
        // 退出当前用户
        subject.logout();
    }

}
